package aiingames.minimax;

import java.util.ArrayList;
import java.util.List;




public class State {
		private int [][] field;
		private int size;
		public static enum Player {MIN,MAX};
		
		public State(int size) {
			this.size = size;
			this.setField(new int[size][size]);
		}
		
		
		
		public List<Action> getActions() {
			List<Action> list = new ArrayList<Action>();
			int max = 0;
			int min = 0;
			for (int i = 0; i < size; i++) {
				for (int j =0; j < size; j++) {
					if (field[i][j] == -1) {
						min++;
					} else if (field[i][j] == 1) {
						max++;
					}
				}
			}
			Player p = null;
			if (max <= min) {
				p = Player.MAX;
			} else {
				p = Player.MIN;
			}
			for (int i = 0; i < size; i++) {
				for (int j =0; j < size; j++) {
					if (field[i][j] == 0) {
						Action a = new Action(i,j,p);
						list.add(a);
					}
				}
			}
			
			return list;
		}
		
		public int utility() {
			
			
			
			if (!terminalTest()) {
				throw new RuntimeException("not a terminal state:\n" + this);
			} 
			
			//columns
			for (int i = 0; i < size; i++) {
				int c = 0;
				for (int j = 0; j < size; j++) {
					c += this.getField()[i][j];
				}
				if (c == size){
					return 1;
				}
				if (c == -size) {
					return -1;
				}
			}
			
			//rows
			for (int j = 0; j < size; j++) {
				int c = 0;
				for (int i = 0; i < size; i++) {
					c += this.getField()[i][j];
				}
				if (c == size){
					return 1;
				}
				if (c == -size) {
					return -1;
				}
			}
			
			

			//diagonal
			//diagonal
			int c = 0;
			for (int i = 0; i < size; i++ ) {
				c += this.getField()[i][i];
			}
			if (c == size){
				return 1;
			}
			if (c == -size) {
				return -1;
			}
			
			c=0;
			for (int i = 0; i < size; i++) {
				int j = size -i - 1;
				c += this.getField()[i][j];
			}
			if (c == size){
				return 1;
			}
			if (c == -size) {
				return -1;
			}
			return 0;
		}
		
		public boolean terminalTest() {
			//columns
			int ones = 0;
			
			for (int i = 0; i < size; i++) {
				int c = 0;
				for (int j = 0; j < size; j++) {
					c += getField()[i][j];
					if (getField()[i][j] != 0) {
						ones++;
					}
				}
				if (Math.abs(c) == size) {
					return true;
				}
			}
			
			if (ones == size*size) {
				return true;
			}

			//rows
			for (int j = 0; j < size; j++) {
				int c = 0;
				for (int i = 0; i < size; i++) {
					c += this.getField()[i][j];
				}
				if (Math.abs(c) == size) {
					return true;
				}
			}
			

			//diagonal
			int c = 0;
			for (int i = 0; i < size; i++ ) {
				c += getField()[i][i];
			}
			if (Math.abs(c) == size) {
				return true;
			}
			
			c=0;
			for (int i = 0; i < size; i++) {
				int j = size -i -1;
				c += getField()[i][j];
			}
			if (Math.abs(c) == size) {
				return true;
			}
			
			return false;		
		}
		
		public String toString() {
			StringBuffer buf = new StringBuffer();
			for (int i = 0; i < size; i++) {
				for (int j = 0; j < size; j++) {
					buf.append('|');
					if (getField()[i][j] == 0) {
						buf.append(' ');
					} else if (getField()[i][j] == 1) {
						buf.append('x');
					} else {
						buf.append('o');
					}
				}
				buf.append('|');
				buf.append('\n');
			}
			
			return buf.toString();
		}

		public void setField(int [][] field) {
			this.field = field;
		}

		public int [][] getField() {
			return field;
		}
}
